package fanshe.load;

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

public class LoadMain {

	private static Consumer<Object> cs = System.out::println;
	
	private static Class<?> loadedOneCls;
	
	private static String clsPath = "fanshe.load.LoadedOne";
	
	public static void main(String[] args) {
		ClassLoader scl = ClassLoader.getSystemClassLoader();
		cs.accept("scl=" + scl);
		
		ClassLoader cl = LoadMain.class.getClassLoader();
		cs.accept("cl =" + cl);
		
		// 返回true：是同一个对象
		cs.accept("scl == cl? = " + (scl == cl));
		
		// 扩展类加载器
		ClassLoader p1 = cl.getParent();
		cs.accept("p1=" + p1);
		
		// 启动类加载器，值为null&mdash;&mdash;因为使用C++实现
		ClassLoader p2 = p1.getParent();
		cs.accept("p2=" + p2);
		
//		try {
//			cs.accept("sleep...20秒后 加载 LoadedOne类...now=" + new Date());
//			TimeUnit.SECONDS.sleep(5);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}

//		try {
//			// 方式1：会执行类初始化
////			Class<?> loadedOneCls = Class.forName(clsPath);
//			// 方式2：不会执行类初始化
//			loadedOneCls = Class.forName(clsPath, false, cl);
//			cs.accept("loadedOneCls=" + loadedOneCls);
//			cs.accept("loadedOneCls=" + loadedOneCls.getSimpleName());
//			cs.accept("loadedOneCls=" + loadedOneCls.getName());
//			cs.accept("loadedOneCls=" + loadedOneCls.getCanonicalName());
//			cs.accept("loadedOneCls=" + loadedOneCls.getTypeName());
//			
//			try {
//				Object nobj = loadedOneCls.newInstance();
//				cs.accept("new obj=" + nobj);
//			} catch (InstantiationException | IllegalAccessException e) {
//				e.printStackTrace();
//			}
//		} catch (ClassNotFoundException e1) {
//			e1.printStackTrace();
//		}
		
//		loadBySystemCl();
		
		// 使用自定义类加载器
//		myLoader1();
		
//		if (true) {
//			cs.accept("....程序结束...now=" + new Date());
//			return;
//		}
		
		// 自定义类加载器
		MyLoader myl = new MyLoader();
		while (true) {
			try {
				cs.accept("5秒后执行类加载...now=" + new Date());
				TimeUnit.SECONDS.sleep(5L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			try {
				dynamicLoadClass2(myl);
				cs.accept("加载完毕，修改类文件，并编译新的class文件...");
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	/**
	 * 使用系统类加载器加载 LoadedOne
	 * @author ben
	 * @date 2021-10-24 17:54:38 CST
	 */
	public static void loadBySystemCl() {
		ClassLoader scl = ClassLoader.getSystemClassLoader();
		try {
			Class<?> newcls = scl.loadClass(clsPath);
			cs.accept("newcls=" + newcls);
			cs.accept("newcls#1=" + newcls.getSimpleName());
			cs.accept("newcls#2=" + newcls.getName());
			cs.accept("newcls#3=" + newcls.getCanonicalName());
			cs.accept("newcls#4=" + newcls.getTypeName());
			
			try {
				Object obj = newcls.newInstance();
				cs.accept("obj=" + obj);
			} catch (InstantiationException | IllegalAccessException e) {
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 动态加载类
	 * @author ben
	 * @throws ClassNotFoundException 
	 * @date 2021-10-20 22:31:03 CST
	 */
	private static void dynamicLoadClass(ClassLoader cl) throws ClassNotFoundException {
		// 方式1：没有加载最新的class文件
//		loadedOneCls = Class.forName(clsPath, false, cl);
		// 方式2：没有加载最新的class文件（同上）
		loadedOneCls = cl.loadClass(clsPath);
		
		try {
			Object nobj = loadedOneCls.newInstance();
			cs.accept("new obj=" + nobj);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 动态加载类：自定义ClassLoader
	 * 失败：使用同一个ClassLoader动态加载
	 * 正确：使用不同的ClassLoader对象执行动态加载
	 * @author ben
	 * @date 2021-10-20 22:56:54 CST
	 * @param cl
	 * @throws ClassNotFoundException
	 */
	private static void dynamicLoadClass2(MyLoader cl) throws ClassNotFoundException {
		// 入参 无法实现 热部署——重新加载类文件
		// 同一个类加载器
		
		// 新建类加载器 才可以 动态加载
		// 怎么使用ClassLoader卸载 已加载的类呢？
		cl = new MyLoader();
		
		loadedOneCls = cl.loadClass("LoadedOne");
		cs.accept("dynamicLoadClass2: loadedOneCls=" + loadedOneCls);
		try {
			Object nobj = loadedOneCls.newInstance();
			cs.accept("2 new obj=" + nobj);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 加载类测试
	 * @author ben
	 * @date 2021-10-24 19:58:50 CST
	 */
	private static void myLoader1() {
		MyLoader ml = new MyLoader();
		cs.accept("MyLoader ml=" + ml);
		cs.accept("MyLoader ml=" + ml.getParent());
		
		// 确保 D:\\LoadedOne.class 文件存在
		final String cls = "LoadedOne";
		try {
			Class<?> newcls = ml.loadClass(cls);
			cs.accept("newcls=" + newcls);
			cs.accept("newcls#1=" + newcls.getSimpleName());
			cs.accept("newcls#2=" + newcls.getName());
			cs.accept("newcls#3=" + newcls.getCanonicalName());
			cs.accept("newcls#4=" + newcls.getTypeName());
			
			Object obj;
			try {
				// 新建对象
				obj = newcls.newInstance();
				cs.accept("new obj=" + obj);
			} catch (InstantiationException | IllegalAccessException e) {
				cs.accept("newInstance()异常：" + e);
			}
		} catch (ClassNotFoundException e) {
			cs.accept("加载失败：" + cls);
			e.printStackTrace();
			return;
		}
	}

}
